﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using GameStateManagement;
using BHG.System;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Controllers;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Factories;
using FarseerPhysics.Common;

namespace BHG.GameData
{
    class Level02 : GameplayScreen
    {
        protected const float MAKE_DYNAMIC_IN_X = 100;
        protected const float MAKE_PLANE_IN_X = 130;

        protected const float BH_RADIUS = 2.0f;
        protected float BH_STRENGHT_BOOST = 0.5f;
        protected const float BLACK_HOLE_SCALE_PS = 0.0025f * 60 * 7;
        protected const float WHEN_LOAD_NEXT_LEVEL = 3f;
        protected readonly Vector2 BH_POSITION = new Vector2(10.0f, 15.0f);
        GravityController BH;
        int blackHoleStrenght = 10;
        float seconds = 0;
        Boolean isPlane = false;
        bool isAirbusTurning = false;

        float infobarAnimationTime = 10f;
        bool startInfoBarAnimation = false;
        bool createdResources = false;

        bool playLeft = false;
        bool playRight = false;
        bool playTop = false;
        bool playBottom = false;

        Model weapon;
        Model bridge;
        Model metalFloor;
        Model metalWall;
        Model cube;
        Model lavicka;
        Model ladders;
        Model woodCube;
        Model plane1;
        Model airbus1;
        Model infoBar;
        Song song;

        SoundEffect middleBlackHoleReverse, f16, planeAround, jetStart2, shotgun;

        BallObject blackHoleObject;
        CubeObject weaponObject;
        bool blackHole = true;
        GraphicObject airbusObject;

        public override void LoadContent()
        {
            base.LoadContent();
            MediaPlayer.Stop();
            PhysicsEngine.Instance.Gravity = new Vector2(0.0f, -20.0f);

            song = content.Load<Song>("Sound/music/03 Departure 91 Master");  // Put the name of your song in instead of "song_title"


            metalFloor = content.Load<Model>("Models/Lands/Metal/metal-floor1");
            metalWall = content.Load<Model>("Models/Walls/metal-wall1");
            bridge = content.Load<Model>("Models/Bridges/most1");
            cube = content.Load<Model>("Models/Cubes/krychle-cihla");
            lavicka = content.Load<Model>("Models/Backgrounds/Benches/lavicka1");
            ladders = content.Load<Model>("Models/Ladders/zebrik1");
            woodCube = content.Load<Model>("Models/Cubes/krychle-drevo");
            weapon = content.Load<Model>("Models/Weapons/weapon1");
            plane1 = content.Load<Model>("Models/Planes/plane1");
            infoBar = content.Load<Model>("Models/Infobars/black-hole-gun-info");
            airbus1 = content.Load<Model>("Models/Planes/airbus1");
            
            planeAround = content.Load<SoundEffect>("Sound/sounds/F-15Taxi");
            middleBlackHoleReverse = content.Load<SoundEffect>("Sound/sounds/middleBlackHoleReverse");
            f16 = content.Load<SoundEffect>("Sound/sounds/f-16");
            jetStart2 = content.Load<SoundEffect>("Sound/sounds/jetstart2");
            shotgun = content.Load<SoundEffect>("Sound/sounds/shotgun-shot");

            player.body.Position = new Vector2(10f, 15f);

            blackHoleObject = new BallObject(BH_POSITION, BH_RADIUS, 0.0f, false, BlackHoleModel, 3f, 300);
            BH = PhysicsEngine.Instance.AddGravityCenter(blackHoleObject, GravityType.DistanceSquared, blackHoleStrenght);
            objectsOnMap.Add(blackHoleObject);

            objectsOnMap.Add(new GraphicObject(
                new Vector2(140, 70),
                infoBar,
                -10
                ));
            weaponObject = new CubeObject(
                new Vector2(
                    -5,
                    15),
                new Vector2(
                    2,
                    2
                    ),
                false,
                weapon
                );
            weaponObject.Scale = 0.01f;
            weaponObject.RotationZ = 1.6f;
            objectsOnMap.Add(weaponObject);

            this.BaseLand(-20, 0, 20);
            this.Gate(50, 15);
            this.BaseLand(180, 15, 5);
            this.BaseLand(160, 30, 5);
            this.BaseLand(180, 45, 5);
            this.BaseLand(160, 60, 5);
            this.BaseLand(-20, 65, 20);
            this.Around(0, 0);
            this.JumpWall(MAKE_DYNAMIC_IN_X, 0);
            this.RotationWall(40, 75);
            this.BaseLand(20, 120, 10);
            this.BaseLand(145, 140, 10);
            this.Airbus(360, 145);


            middleBlackHoleReverse.Play();
        }

        /// <summary>
        ///  Update base, then update level.
        /// </summary>
        /// 
        /// <param name="gameTime"></param>
        /// <param name="otherScreenHasFocus"></param>
        /// <param name="coveredByOtherScreen"></param>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            // generic update, update physics, call only once
            base.Update(gameTime, otherScreenHasFocus, false);

            if (player.Position.X < 0)
            {
                startInfoBarAnimation = true;
            }

            if (startInfoBarAnimation == true)
            {
                infobarAnimationTime -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (createdResources == false)
                {
                    CreateShowInfobar();
                    top.Scale = 0.001f;
                    bottom.Scale = 0.001f;
                    left.Scale = 0.001f;
                    right.Scale = 0.001f;
                    createdResources = true;
                    weaponObject.state = State.REMOVED;
                }
            }

            if ((infobarAnimationTime < 10) && ( infobarAnimationTime > 5)){
                blackHoleWeaponTime = TIME_TO_REFRESH_BLACKHOLEGUN;
            }

            if ((infobarAnimationTime < 10) && (infobarAnimationTime > 9)){
                left.Scale = (10 - infobarAnimationTime) / 10;
            }
            if ((infobarAnimationTime < 9) && (infobarAnimationTime > 8))
            {
                if (playLeft == false)
                {
                    playLeft = true;
                    shotgun.Play();
                }
                left.Scale = 0.1f;
                right.Scale = (9 - infobarAnimationTime) / 10;
            }
            if ((infobarAnimationTime < 8) && (infobarAnimationTime > 7))
            {
                if (playRight == false)
                {
                    playRight = true;
                    shotgun.Play();
                }
                right.Scale = 0.1f;
                top.Scale = (8 - infobarAnimationTime) / 10;
            }
            if ((infobarAnimationTime < 7) && (infobarAnimationTime > 6))
            {
                if (playTop == false)
                {
                    playTop = true;
                    shotgun.Play();
                }
                top.Scale = 0.1f;
                bottom.Scale = (7 - infobarAnimationTime) / 10;
            }

            if ((infobarAnimationTime < 6) && (infobarAnimationTime > 5))
            {
                if (playBottom == false)
                {
                    playBottom = true;
                    shotgun.Play();
                    blackHoleGunAllowed = true;
                    MediaPlayer.Play(song);
                }
                bottom.Scale = 0.1f;
            }

            weaponObject.body.LinearVelocity = new Vector2(0, weaponObject.body.LinearVelocity.Y);

            if ((player.Position.X > 340) && (player.Position.Y > 130))
            {
                if (airbusObject.RotationZ >= 1.6f)
                {
                    if (isAirbusTurning)
                    {
                        jetStart2.Play();
                        airbusObject.SpeedPerSecond = new Vector3(0, 0, -170);
                        airbusObject.RotationPerSecond = new Vector3(0, 0, 0);
                        isAirbusTurning = false;
                    }
                }
                else
                {
                    if (isAirbusTurning == false)
                    {
                        isAirbusTurning = true;
                        airbusObject.RotationPerSecond = new Vector3(0, 0, 0.1f);
                        planeAround.Play();
                    }
                }
                player.body.LinearVelocity = new Vector2(0, 0);
                player.RotationZ = airbusObject.RotationZ-1.6f;
                player.Depth = airbusObject.Depth-18;
                cameraMove = true;
            }

            if (player.Depth < -1700)
            {
                LoadingScreen.Load(ScreenManager, true, PlayerIndex.One, CurrentGame.createNewLevel(3));
            }

            if ((isPlane == false) && (player.Position.X > MAKE_PLANE_IN_X))
            {
                GraphicObject tempObj = new GraphicObject(
                                    new Vector2(MAKE_PLANE_IN_X + 40, -70),
                                    plane1,
                                    0f
                                    );
                tempObj.Depth = 100f;
                tempObj.Scale = 0.01f;
                tempObj.SpeedPerSecond = new Vector3(0f, 0f, -400f);
                isPlane = true;
                f16.Play();

                objectsOnMap.Add(tempObj);
            }

            if (player.Position.X > MAKE_DYNAMIC_IN_X)
            {
                foreach (Body body in PhysicsEngine.Instance.gameWorld.BodyList)
                {
                    if ((body.Position.X > MAKE_DYNAMIC_IN_X - 1) && (body.Position.X < MAKE_DYNAMIC_IN_X + 2) && (body.Position.Y > 0) && (body.Position.Y < 20))
                    {
                        body.IsStatic = false;
                    }
                }
            }

            if (player.body.Position.Y < -30f)
            {
                Death();
            }

            if (blackHole == true)
            {
                float time = (float)gameTime.ElapsedGameTime.TotalSeconds;

                blackHoleObject.Rotation += 0.1f;
                blackHoleObject.RotationY += 0.01f;
                blackHoleObject.RotationZ += 0.01f;

                BH.Strength -= BH_STRENGHT_BOOST;

                blackHoleObject.Scale -= BLACK_HOLE_SCALE_PS * time;
                if (blackHoleObject.Scale <= 0f)
                {
                    blackHoleObject.state = State.REMOVED;
                    BH.Strength = 0f;
                    blackHole = false;
                    if (player.Position.X > 0)
                    {
                        weaponObject.body.IsStatic = false;
                    }

                    CubeObject lavickaObject = new CubeObject(
                                       new Vector2(
                                           10,
                                           10),
                                       new Vector2(
                                           10f,
                                           3f),
                                           0f,
                                       true,
                                       lavicka,
                                       3f
                                       );
                    lavickaObject.Dislocation = new Vector3(0, -2f, 0);
                    lavickaObject.body.LinearVelocity = new Vector2(-40f, 60f);
                    objectsOnMap.Add(lavickaObject);

                }

                seconds += (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (seconds >= 0.2f)
                {
                    createCube(10, 15);
                    seconds -= 0.2f;
                }
            }
        }

        public void JumpWall(float x, float y)
        {
            CubeObject tempCube;
            float thick = 2f;

            for (int i = 0; i < 10; i++)
            {
                tempCube = new CubeObject(
                    new Vector2(
                        x,
                        y + i * thick),
                    new Vector2(
                        thick,
                        thick
                        ),
                    false,
                    woodCube
                    );
                objectsOnMap.Add(tempCube);
            }
        }

        public void Death()
        {
            LoadingScreen.Load(ScreenManager, true, PlayerIndex.One, CurrentGame.createNewLevel(2));
        }

        public void OneAround(float x, float y, float depth, float plusX, float plusY, float plusZ, int count)
        {
            GraphicObject tempObject;
            Random random = new Random();
            float randomDevide = 3f;
            for (int i = 0; i < count; i++)
            {
                tempObject = new GraphicObject(
                    new Vector2(x + i * plusX, y + i * plusY),
                    metalFloor,
                    0f
                    );
                tempObject.Depth = depth - i * plusZ;
                tempObject.RotationPerSecond = new Vector3((float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide);
                objectsOnMap.Add(tempObject);
            }
        }

        public void Around(int x, int y)
        {
            GraphicObject tempObject;
            Random random = new Random();
            float randomDevide = 3f;

            OneAround(140, -60, -15, 14, 7, 4, 50);
            for (int i = 0; i < 50; i++)
            {
                float depthThick;
                depthThick = 10f;
                tempObject = new GraphicObject(
                    new Vector2(x - 10f, y - 15f),
                    metalFloor,
                    0f
                    );
                tempObject.Depth = 30f - i * depthThick;
                tempObject.RotationPerSecond = new Vector3((float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide);
                objectsOnMap.Add(tempObject);

                tempObject = new GraphicObject(
                    new Vector2(x + 40f, y + 20f),
                    metalFloor,
                    0f
                    );
                tempObject.Depth = 30f - i * depthThick;
                tempObject.RotationPerSecond = new Vector3((float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide);
                objectsOnMap.Add(tempObject);

                tempObject = new GraphicObject(
                    new Vector2(x - 120f + i * depthThick, y - 25f),
                    metalFloor,
                    0f
                    );
                tempObject.Depth = -100;
                tempObject.RotationPerSecond = new Vector3((float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide);
                objectsOnMap.Add(tempObject);

                tempObject = new GraphicObject(
                    new Vector2(x - 120f + i * depthThick, y + 15f),
                    metalFloor,
                    0f
                    );
                tempObject.Depth = -60;
                tempObject.RotationPerSecond = new Vector3((float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide);
                objectsOnMap.Add(tempObject);

                tempObject = new GraphicObject(
                    new Vector2(x + 50f + i * depthThick, y - 40f + i * depthThick),
                    metalFloor,
                    0f
                    );
                tempObject.Depth = 10;
                tempObject.RotationPerSecond = new Vector3((float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide, (float)random.NextDouble() / randomDevide);
                objectsOnMap.Add(tempObject);
            }
        }

        public void Gate(int x, int y)
        {
            for (int j = 0; j < 4; j++)
            {
                CubeObject tempCube;
                Vector2 thickLadder = new Vector2(1f, 3f);
                for (int i = 0; i < 10; i++)
                {
                    tempCube = new CubeObject(
                        new Vector2(
                            x + j * 10,
                            y + i * thickLadder.Y),
                        new Vector2(
                            thickLadder.X,
                            thickLadder.Y
                            ),
                        false,
                        ladders
                        );
                    objectsOnMap.Add(tempCube);
                    tempCube = new CubeObject(
                        new Vector2(
                            x + 3f + j * 10,
                            y + i * thickLadder.Y),
                        new Vector2(
                            thickLadder.X,
                            thickLadder.Y
                            ),
                        false,
                        ladders
                        );
                    objectsOnMap.Add(tempCube);
                }

                tempCube = new CubeObject(
                    new Vector2(
                        x + 1.5f + j * 10,
                        y),
                    new Vector2(
                        thickLadder.X,
                        30
                        ),
                    true,
                    metalWall
                    );
                tempCube.Dislocation = new Vector3(0f, -15f, 0f);
                objectsOnMap.Add(tempCube);

            }
        }

        public void createCube(int x, int y)
        {
            Random random = new Random();
            float thick = 2f;
            CubeObject tempCube = new CubeObject(
                new Vector2(
                    x + (float)random.NextDouble() * 10 - 5f,
                    y + (float)random.NextDouble() * 10 - 5f),
                new Vector2(
                    thick,
                    thick),
                true,
                cube);
            tempCube.Life = 5;
            tempCube.body.LinearVelocity = new Vector2((float)random.NextDouble() * 30 - 15f, (float)random.NextDouble() * 30 - 15f);
            objectsOnMap.Add(tempCube);
        }

        /// <summary>
        /// Create the base objects where you can walk
        /// </summary>
        /// <param name="positionX"></param>
        /// <param name="positionY"></param>
        public void BaseLand(float positionX, float positionY, int count)
        {

            //Here you can walk
            float thick = 10f;
            float thickUp = 1f;
            for (int i = 0; i < count; i++)
            {
                objectsOnMap.Add(new CubeObject(
                    new Vector2(
                        positionX + i * thick,
                        positionY),
                    new Vector2(
                        thick,
                        thickUp),
                    false,
                    metalFloor
                    ));
            }
        }

        public void RotationWall(float x, float y)
        {
            Vector2 thickLadder = new Vector2(13f, 2f);
            for (int i = 0; i < 5; i++)
            {
                CubeObject tempCube = new CubeObject(
                    new Vector2(
                        x-i*10,
                        y+i*10),
                    new Vector2(
                        thickLadder.X,
                        thickLadder.Y
                        ),
                    false,
                    metalFloor
                    );
                tempCube.RotationPerSecond = new Vector3(0.5f, 0, 0);
                objectsOnMap.Add(tempCube);
            }
        }

        //public void CubesOnRamp(float x, float y)
        //{
        //    Vector2 thickLadder = new Vector2(2f, 2f);
        //    float yUp = 5f;
        //    CubeObject tempCube = new CubeObject(
        //        new Vector2(
        //            x,
        //            y - 2 * thickLadder.Y + yUp),
        //        new Vector2(
        //            thickLadder.X,
        //            thickLadder.Y
        //            ),
        //        false,
        //        woodCube
        //        );
        //    objectsOnMap.Add(tempCube);

        //    for (int i = 0; i < 25; i++)
        //    {
        //        tempCube = new CubeObject(
        //            new Vector2(
        //                x,
        //                y + i * thickLadder.Y + yUp),
        //            new Vector2(
        //                thickLadder.X,
        //                thickLadder.Y
        //                ),
        //            false,
        //            woodCube
        //            );
        //        objectsOnMap.Add(tempCube);
        //    }

        //    tempCube = new CubeObject(
        //        new Vector2(
        //            x + 9f,
        //            y - 2 * thickLadder.Y + yUp),
        //        new Vector2(
        //            thickLadder.X,
        //            thickLadder.Y
        //            ),
        //        false,
        //        woodCube
        //        );
        //    objectsOnMap.Add(tempCube);

        //    for (int i = 0; i < 25; i++)
        //    {
        //        tempCube = new CubeObject(
        //            new Vector2(
        //                x+9f,
        //                y + i * thickLadder.Y + yUp),
        //            new Vector2(
        //                thickLadder.X,
        //                thickLadder.Y
        //                ),
        //            false,
        //            woodCube
        //            );
        //        objectsOnMap.Add(tempCube);
        //    }


        //    tempCube = new CubeObject(
        //        new Vector2(
        //            x+4.5f,
        //            y - 2f + yUp),
        //        new Vector2(
        //            10,
        //            1
        //            ),
        //        true,
        //        metalFloor
        //        );
        //    objectsOnMap.Add(tempCube);

        //    //Now the box
        //    tempCube = new CubeObject(
        //        new Vector2(
        //            x - 6f,
        //            y - 30f),
        //        new Vector2(
        //            1,
        //            30
        //            ),
        //        false,
        //        metalWall
        //        );
        //    tempCube.Dislocation = new Vector3(0,-10f,0);
        //    objectsOnMap.Add(tempCube);

        //    for (int i = 0; i < 3; i++)
        //    {
        //        tempCube = new CubeObject(
        //            new Vector2(
        //                x - 1+i*10,
        //                y - 30),
        //            new Vector2(
        //                10,
        //                1
        //                ),
        //            false,
        //            metalFloor
        //            );
        //        objectsOnMap.Add(tempCube);
        //    }

        //    //Very much dynamic boxes
        //    for (int i = 0; i < 10; i++)
        //    {
        //        tempCube = new CubeObject(
        //            new Vector2(
        //                x +4,
        //                y +5 +i*2),
        //            new Vector2(
        //                2,
        //                2
        //                ),
        //            true,
        //            woodCube
        //            );
        //        objectsOnMap.Add(tempCube);
        //    }
        //}

        public void Airbus(float x, float y)
        {
            airbusObject = new GraphicObject(
                new Vector2(x, y),
                airbus1,
                0f
                );
            airbusObject.Scale = 0.1f;
            airbusObject.Depth = 18;
            objectsOnMap.Add(airbusObject);

            Body body = BodyFactory.CreateBody(PhysicsEngine.Instance.gameWorld);
            body.CreateFixture(new PolygonShape(PolygonTools.CreateRectangle(100, 3)));
            body.BodyType = BodyType.Static;
            body.Position = new Vector2(x,y-13);
            body.Rotation = 0;           
        }
    }
}
